"""IPAM相关模型."""

import ipaddress
from datetime import datetime
from typing import Optional

from sqlalchemy import (
    Boolean,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .base import Base


class VRF(Base):
    """虚拟路由转发实例模型."""
    
    __tablename__ = "vrf"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    rd: Mapped[str] = mapped_column(String(21), unique=True, nullable=False)  # Route Distinguisher
    description: Mapped[Optional[str]] = mapped_column(Text)
    enforce_unique: Mapped[bool] = mapped_column(Boolean, default=True)
    
    # 关联
    networks: Mapped[list["IPNetwork"]] = relationship(
        "IPNetwork", back_populates="vrf", cascade="all, delete-orphan"
    )


class VLAN(Base):
    """VLAN模型."""
    
    __tablename__ = "vlan"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    vid: Mapped[int] = mapped_column(Integer, unique=True, nullable=False)  # VLAN ID
    name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text)
    
    # 关联
    networks: Mapped[list["IPNetwork"]] = relationship(
        "IPNetwork", back_populates="vlan"
    )


class IPNetwork(Base):
    """IP网络模型."""
    
    __tablename__ = "ip_network"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    network: Mapped[str] = mapped_column(String(43), nullable=False)  # IPv4/IPv6网络地址
    prefix_length: Mapped[int] = mapped_column(Integer, nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text)
    
    # 外键关联
    vrf_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("vrf.id"), nullable=True
    )
    vlan_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("vlan.id"), nullable=True
    )
    
    # 状态字段
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    total_addresses: Mapped[int] = mapped_column(Integer, default=0)
    used_addresses: Mapped[int] = mapped_column(Integer, default=0)
    
    # 关联
    vrf: Mapped[Optional["VRF"]] = relationship("VRF", back_populates="networks")
    vlan: Mapped[Optional["VLAN"]] = relationship("VLAN", back_populates="networks")
    addresses: Mapped[list["IPAddress"]] = relationship(
        "IPAddress", back_populates="network", cascade="all, delete-orphan"
    )
    
    # 约束
    __table_args__ = (
        UniqueConstraint("network", "prefix_length", "vrf_id", name="uq_network_vrf"),
        Index("idx_network_vrf", "vrf_id"),
        Index("idx_network_vlan", "vlan_id"),
    )
    
    @property
    def cidr(self) -> str:
        """获取CIDR表示法."""
        return f"{self.network}/{self.prefix_length}"
    
    @property
    def network_obj(self) -> ipaddress.IPv4Network | ipaddress.IPv6Network:
        """获取网络对象."""
        return ipaddress.ip_network(self.cidr)


class IPAddress(Base):
    """IP地址模型."""
    
    __tablename__ = "ip_address"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    address: Mapped[str] = mapped_column(String(39), nullable=False)  # IPv4/IPv6地址
    
    # 外键关联
    network_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("ip_network.id"), nullable=False
    )
    
    # 基本信息
    hostname: Mapped[Optional[str]] = mapped_column(String(255))
    description: Mapped[Optional[str]] = mapped_column(Text)
    
    # 状态字段
    status: Mapped[str] = mapped_column(
        String(20), 
        default="available", 
        nullable=False
    )  # available, reserved, assigned, deprecated
    
    # MAC地址（用于DHCP）
    mac_address: Mapped[Optional[str]] = mapped_column(String(17))
    
    # DHCP租约信息
    dhcp_lease_id: Mapped[Optional[int]] = mapped_column(
        Integer, ForeignKey("dhcp_lease.id"), nullable=True
    )
    
    # DNS记录
    dns_records: Mapped[list["DNSRecord"]] = relationship(
        "DNSRecord", back_populates="ip_address"
    )
    
    # 关联
    network: Mapped["IPNetwork"] = relationship("IPNetwork", back_populates="addresses")
    dhcp_lease: Mapped[Optional["DHCPLease"]] = relationship("DHCPLease")
    
    # 约束
    __table_args__ = (
        UniqueConstraint("address", "network_id", name="uq_address_network"),
        Index("idx_address_network", "network_id"),
        Index("idx_address_status", "status"),
    )
    
    @property
    def ip_obj(self) -> ipaddress.IPv4Address | ipaddress.IPv6Address:
        """获取IP地址对象."""
        return ipaddress.ip_address(self.address)
    
    @property
    def is_available(self) -> bool:
        """检查地址是否可用."""
        return self.status == "available"
    
    @property
    def is_reserved(self) -> bool:
        """检查地址是否保留."""
        return self.status == "reserved"
    
    @property
    def is_assigned(self) -> bool:
        """检查地址是否已分配."""
        return self.status == "assigned"